import os
import json
from abc import ABC, abstractmethod


class BaseConf(ABC):
    def __init__(self, path: str):
        """配置基本类"""
        self.path = path
        self.filename = os.path.split(self.path)[1]
        self.load_success = True
        # 文件存在时加载，否则生成默认配置
        if os.path.exists(self.path):
            self.reload()
        else:
            self.reload_from_str("{}")
        # 保存配置至文件(同时补全)
        # 读取配置异常时不覆盖用户内容
        if self.load_success:
            self.save()

    def __load_file(self) -> dict:
        """读取json文件获取解析"""
        data = {}
        try:
            with open(self.path, "rb") as f:
                data = json.loads(f.read())
        except json.decoder.JSONDecodeError:
            self.load_success = False
            print(f"[DLS][ERROR] 配置文件{self.filename}格式有误！将使用默认配置")
        except Exception as e:
            self.load_success = False
            print(f"[DLS][ERROR] 配置文件{self.filename}加载失败: {e}！将使用默认配置")
        return data

    def __save_file(self, text: str):
        """保存字符串至json文件"""
        with open(self.path, "w", encoding="utf-8") as f:
            f.write(text)

    def reload(self):
        """读取文件为加载配置"""
        conf_dict = self.__load_file()
        self._reload_from_dict(conf_dict)
        self._check()

    def reload_from_str(self, text: str):
        """从字符串读取配置文件"""
        conf_dict = self._str_to_dict(text)
        self._reload_from_dict(conf_dict)
        self._check()

    def save(self):
        """保存配置至文件中"""
        self.__save_file(self.__str__())

    def get_dict(self) -> dict:
        """返回dict类型配置"""
        return json.loads(self.__str__())

    def update_from_dict(self, new_dict: dict):
        """从新字典更新配置"""
        conf_dict = self._str_to_dict(self.__str__())
        conf_dict.update(new_dict)
        self._reload_from_dict(conf_dict)

    @staticmethod
    def _dict_to_str(data: dict) -> str:
        return json.dumps(data, indent=2, ensure_ascii=False)

    @staticmethod
    def _str_to_dict(text: str) -> dict:
        return json.loads(text)

    @abstractmethod
    def _reload_from_dict(self, conf_dict: dict):  # pragma: no cover
        """从字典初始化配置"""
        pass

    @abstractmethod
    def _check(self):  # pragma: no cover
        """对配置进行检查"""
        pass

    @abstractmethod
    def __str__(self) -> str:  # pragma: no cover
        """从配置生成字符串"""
        pass
